package com.caiyi.financial.nirvana.sms.server;

import com.caiyi.financial.nirvana.sms.gateway.cmpp.cmpp20.message.CMPPMessage;
import com.caiyi.financial.nirvana.sms.gateway.cmpp.cmpp20.message.body.CMPPActiveTest;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.util.AttributeKey;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.SocketAddress;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * CMPP服务器总控制器
 */
public class CMPPServerControlHandler extends ChannelDuplexHandler {

    private static final Logger logger = LoggerFactory.getLogger(CMPPServerControlHandler.class);
    public static final AtomicInteger seqNo = new AtomicInteger(1);

    @Override
    public void connect(ChannelHandlerContext ctx, SocketAddress remoteAddress, SocketAddress localAddress, ChannelPromise future) throws Exception {
        logger.debug("正在连接");
        super.connect(ctx, remoteAddress, localAddress, future);
    }

    @Override
    public void close(ChannelHandlerContext ctx, ChannelPromise future) throws Exception {
        super.close(ctx, future);
    }

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        super.write(ctx, msg, promise);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        AttributeKey<String> accountKey = AttributeKey.valueOf("account");
        String account = ctx.channel().attr(accountKey).get();
        if (StringUtils.isNotBlank(account)) {
            AccountHolder holder = CmppServerHandler.accountHolders.remove(account);
            holder.shutdown();
        }
        super.channelInactive(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg)
            throws Exception {
        super.channelRead(ctx, msg);
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        logger.error(cause.getMessage(), cause);
    }

    @Override
    //客户端空闲时间过长，发送心跳测试
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        //通道没有客户登录，则关闭
        AttributeKey<String> accountKey = AttributeKey.valueOf("account");
        String account = ctx.channel().attr(accountKey).get();
        if (StringUtils.isBlank(account)) {
            ctx.channel().close();
            return;
        }
        //发送心跳测试
        AttributeKey<String> activeKey = AttributeKey.valueOf("active");
        String active = ctx.channel().attr(activeKey).get();
        if (StringUtils.isNotBlank(active)) {
            //通道的active属性不为空，说明未收到心跳回复，直接断开连接
            ctx.channel().close();
        } else {
            //未发送过心跳测试或者收到过心跳回复，则重新发起心跳测试
            logger.info("account:" + account + " 触发心跳测试。");
            ctx.channel().attr(activeKey).set("active");
            CMPPMessage message = new CMPPMessage();
            message.setCommandID(CMPPMessage.CMPP_ACTIVE_TEST);
            message.setSequenceId(seqNo.decrementAndGet());
            CMPPActiveTest activeTest = new CMPPActiveTest();
            message.setBody(activeTest);
            ctx.writeAndFlush(message);
        }
    }
}
